<?php

require_once($WSC->get_site_inc_dir().'_sys/site_web_page_wed.class.php');
require_once($WSC->get_site_inc_dir().'modules/admin_panel/forms/admin_login/admin_login_form.class.php');
require_once($WSC->get_site_inc_dir().'modules/admin_panel/forms/admin_login/admin_login_form_view.class.php');
require_once($WSC->get_site_inc_dir().'modules/user_auth_basic/classes/cookie_user_dbc.class.php');
require_once($WSC->get_site_inc_dir().'modules/user_auth_basic/classes/user_activity_dbc.class.php');
require_once($WSC->get_site_inc_dir().'modules/user_auth_basic/classes/user_activity_type_dbc.class.php');
require_once($WSC->get_site_inc_dir().'modules/admin_panel/classes/admin_user/admin_user_dbc.class.php');


class Login_WP extends Site_Web_Page_WED {
	private $form;
	private $form_view;

	private $return_to = '';
	private $return_to_params_raw = '';

	private $ua_config;
	private $user_dbc_class = 'User_BFPwd_DBC'; // intentionally hardcoded. Admin panel must use blowfish + salt


	function __construct($page_name, $ua_config) {
		parent::__construct($page_name);
		$this->set_ua_config($ua_config);
	}


	public function set_ua_config($ua_config) {
		$this->ua_config = $ua_config;
	}


	public function get_ua_config() {
		return $this->ua_config;
	}

	
	public function get_user_dbc_class() {
		return $this->user_dbc_class;
	}	
	

	public function init() {
		parent::init();

		$this->check_ssl_required();
		
		$v = new Site_Web_Page_View($this, 'default', 'modules/admin_panel/pages/');
		$this->add_view($v);

		$this->wed->add_wed_event_action_pair(new Web_Event_Simple('logout', Tangra_Parameter_Method::GET, 'logout'), 'logout_event');
		$this->wed->add_wed_event_action_pair(new Web_Event_Simple('submit', Tangra_Parameter_Method::POST, 'login_form_submit'), 'submit_event');
		$this->wed->add_wed_event_action_pair(new Web_Event_Simple('submit_x', Tangra_Parameter_Method::POST, 'login_form_submit_x'), 'submit_event');
		
		$config = $this->get__config();
		$this->export('site_name', $config->get_site_name());
		$user_provided_logo = $config->get_htdocs_dir().'img/admin_panel_logo.png'; 
		if (file_exists($user_provided_logo)) {
			$this->export('logo_img', "img/admin_panel_logo.png");
		} else {
			$this->export('logo_img', "img/modules/admin_panel/logo.png");
			$this->export('default_logo', 1);
		}
	}

	
	public function default_event() {
		$ua_config = $this->get_ua_config();
		
		$this->init_return_to();
	
		$svm = $this->get_svm();				
		if ($svm->is_global_var_registered($ua_config['session_var_name'])) {
			// user is already logged so we redirect to default page
			$user = $svm->get_global_var($ua_config['session_var_name']);
			$ret = $this->_create_redirect_view();
		} else {
			global $_VISITOR_COOKIE;
			if ($_VISITOR_COOKIE) {
				$ret = $this->cookie_exist_case($_VISITOR_COOKIE->get_id());
			} else {
				$this->prepare_form();
				$ret = $this->form_mode(); 
			}
		}

		return $ret;
	}
	
	
	public function logout_event() {
		$ua_config = $this->get_ua_config();

		global $_VISITOR_COOKIE;
		if ($_VISITOR_COOKIE) {
			$cookie_id = $_VISITOR_COOKIE->get_id();

			$cookie_user = new Cookie_User_DBC($ua_config['db_tables_prefix']);
			$dbc = $this->get_dbc();
			if ($cookie_user->load_by_cookie_id($dbc, $cookie_id)) {
				$this->delete_cookie_user($cookie_user->get_id());
			}
		}
		
		$svm = $this->get_svm();

		//first checking if session is not expired
		if ($svm->is_global_var_registered($ua_config['session_var_name'])) {
			$user = $svm->get_global_var($ua_config['session_var_name']);
			$dbc = $this->get_dbc();
			$this->log_logout($dbc, $user->get_id());
		}

		session_destroy();

		if ($ua_config['require_ssl_login']) {
			$redir_composer = new Redirect_Composer_Local($this->get__context(), $ua_config['login_page'], array(), 'https');
		} else {
			$redir_composer = new Redirect_Composer_Local($this->get__context(), $ua_config['login_page'], array());
		}
		$redir_view = new Just_Headers_View();
		$redir_view->add_http_header($redir_composer->get_location($this->get__context()));

		return $redir_view;
	}


	public function submit_event() {
		$this->prepare_form();

		$context = $this->get__context();

		$this->form->capture_submit($context);
		$this->form->basic_check();
		$this->form->accept_submit();


		if ($this->form->is_form_ok()) {
			$username = $this->form->get_field_value('username');
			$password = $this->form->get_field_value('password');
			$remember = $this->form->get_field_value('remember');

			$this->return_to = $this->form->get_field_value('return_to');
			$this->return_to_params_raw = $this->form->get_field_value('return_to_params');

			$dbc = $this->get_dbc();
			$user = $this->check_login($dbc, $username, $password);

			if ($user) {
				$ret = $this->login($user, $remember);
			} else {
				// Shows error "Invalid login"
				$this->form->set_field_error('password', 'invalid_login');
				$ret =  $this->form_mode();
			}
		} else {
			$ret = $this->form_mode();
		}

		return $ret;
	}
	
	
	private function cookie_exist_case($cookie_id) {
		$ua_config = $this->get_ua_config();		

		$cookie_user = new Cookie_User_DBC($ua_config['db_tables_prefix']);
		$dbc = $this->get_dbc();
		if ($cookie_user->load_by_cookie_id($dbc, $cookie_id)) {
			$return_to_params = $this->prepare_return_to_params($this->return_to_params_raw);
						
			if ($ua_config['remember_me_max_period']) {
				$ret = $this->remember_max_period_nonzero_case($ua_config['remember_me_max_period'], $cookie_user);
			} else {
				// max period is disabled so we just login (i.e. == 0)
				$user = $this->load_user($cookie_user->get_user());
				if ($user !== false) {
					$ret = $this->_login($user, $this->return_to, $return_to_params, true);
				} else {
					$this->prepare_form();
					$ret = $this->form_mode();
				}
			}				
		} else {
			$this->prepare_form();
			$ret = $this->form_mode();				
		}	

		return $ret;
	}
	
	
	private function remember_max_period_nonzero_case($period, Cookie_User_DBC $cookie_user) {
		$ua_config = $this->get_ua_config();
		
		if ($cookie_user->get_ts() + $ua_config['remember_me_max_period'] < time()) { // max remember period reached
			$this->delete_cookie_user($cookie_user->get_id());

			$this->prepare_form();
			$ret = $this->form_mode();
		} else {
			$user = $this->load_user($cookie_user->get_user());
			if ($user !== false) {
				$return_to_params = $this->prepare_return_to_params($this->return_to_params_raw);
				$ret = $this->_login($user, $this->return_to, $return_to_params, true);
			} else {
				$this->prepare_form();
				$ret = $this->form_mode();
			}
		}		
		
		return $ret;
	}
	
	
	private function delete_cookie_user($cookie_user_id) {
		tangra_if_not_int_throw_e($cookie_user_id);
		$dbc = $this->get_dbc();
		$ua_config = $this->get_ua_config();
		try {
			$dbc->start_trans();
			Cookie_User_DBC::delete($dbc, $cookie_user_id, $ua_config['db_tables_prefix']);
			$dbc->complete_trans();
		} catch (Exception $e) {
			$dbc->fail_trans();
			$dbc->complete_trans();
			throw $e;
		}			
	}
	
	
	private function load_user($user_id) {
		$ret = false;
	
		$user_dbc_class = $this->get_user_dbc_class();
		$ua_config = $this->get_ua_config();
		$user = new $user_dbc_class($ua_config['db_tables_prefix']);
		$dbc = $this->get_dbc();
		if ($user->load_by_id($dbc, $user_id) !== false) {
			$ret = $user;
		}
		
		return $ret;
	}
	
	
	private function prepare_return_to_params($return_to_params_raw) {
		$return_to_params = array();
		$params_raw_arr = explode('&', urldecode($return_to_params_raw));
		foreach($params_raw_arr as $param_raw) {
			$tmp_arr = explode('=', $param_raw);
			if (array_key_exists(1, $tmp_arr)) {
				$return_to_params[$tmp_arr[0]] = $tmp_arr[1];
			}
		}					
		
		return $return_to_params;
	}


	private function form_mode() {
		$this->add_exports($this->form_view->get_tple_exports());
		$view = $this->get_view('default');

		return $view;
	}


	private function prepare_form() {
		$this->form = new Admin_Login_Form('login', 'admin/login.php');

		$this->form->set_field_value('return_to', $this->return_to);
		$this->form->set_field_value('return_to_params', urlencode($this->return_to_params_raw));

		$this->form->set_field_value('remember', false);

		$this->form_view = new Admin_Login_Form_View($this->form);

//		$this->form->generate_html();
	}


	private function check_login(DB_Connection $dbc, $username, $password) {
		$ret = false;

		$ua_config = $this->get_ua_config();
		
		$user_dbc_class = $this->get_user_dbc_class();
		$user = $user_dbc_class::check_login($dbc, $username, $password, $ua_config['db_tables_prefix']);
		if ($user) {
			$ret = $user;
		}

		return $ret;
	}


	private function log_login($user_id, $remember = false) {
		$dbc = $this->get_dbc();
		$ua_config = $this->get_ua_config();

		$uat = new User_Activity_Type_DBC($ua_config['db_tables_prefix']);
		if ($uat->load_by_hid($dbc, 'login')) {
			$ua = new User_Activity_DBC($ua_config['db_tables_prefix']);
			$ua->set_user($user_id);
			$ua->set_type($uat->get_id());

			$context = $this->get__context();
			$ua->set_data(array($context->get_from_server('REMOTE_ADDR'), $remember));

			try {
				$dbc->start_trans();
				$ua->save($dbc);
				$dbc->complete_trans();
			} catch (Exception $e) {
				$dbc->fail_trans();
				$dbc->complete_trans();
				throw $e;
			}
		}
	}

	private function log_logout(DB_Connection $dbc, $user_id) {
		$ua_config = $this->get_ua_config();

		$uat = new User_Activity_Type_DBC($ua_config['db_tables_prefix']);
		if ($uat->load_by_hid($dbc, 'logout')) {
			$ua = new User_Activity_DBC($ua_config['db_tables_prefix']);
			$ua->set_user($user_id);
			$ua->set_type($uat->get_id());

			try {
				$dbc->start_trans();
				$ua->save($dbc);
				$dbc->complete_trans();
			} catch (Exception $e) {
				$dbc->fail_trans();
				$dbc->complete_trans();
				throw $e;
			}
		}
	}


	private function login($user, $remember) {
		$dbc = $this->get_dbc();

		global $_VISITOR_COOKIE;
		if ($_VISITOR_COOKIE) {
			$cookie_id = $_VISITOR_COOKIE->get_id();

			$ua_config = $this->get_ua_config();
			$cookie_user = new Cookie_User_DBC($ua_config['db_tables_prefix']);

			if ($remember) {
				if (!$cookie_user->load_by_cookie_id($dbc, $cookie_id)) {
					$cookie_user->set_cookie($cookie_id);
					$cookie_user->set_user($user->get_id());
					try {
						$dbc->start_trans();
						$cookie_user->save($dbc);
						$dbc->complete_trans();
					} catch (Exception $e) {
						$dbc->fail_trans();
						$dbc->complete_trans();
						throw $e;
					}
				}
			} else {
				if ($cookie_user->load_by_cookie_id($dbc, $cookie_id)) {
					try {
						$dbc->start_trans();
						Cookie_User_DBC::delete($dbc, $cookie_user->get_id(), $ua_config['db_tables_prefix']);
						$dbc->complete_trans();
					} catch (Exception $e) {
						$dbc->fail_trans();
						$dbc->complete_trans();
						throw $e;
					}
				}
			}
		}

		$return_to_params = array();
		$return_to = ''; 
		if ($this->form->get_field_value('return_to')) {
			$return_to = $this->form->get_field_value('return_to');
			$return_to_params = $this->prepare_return_to_params($this->form->get_field_value('return_to_params'));
		} 

		return $this->_login($user, $return_to, $return_to_params);
	}
	
	
	private function _login(User_DBC $user, $return_to, $return_to_params, $remember = false) {
		$this->log_login($user->get_id(), $remember);
		$this->set_session_user_var($user);

		$redir_view = $this->_create_redirect_view($return_to, $return_to_params);
		
		return $redir_view;
	}
	
	
	private function set_session_user_var($user) {
		$ua_config = $this->get_ua_config();
		
		// Registers session var for current user
		$svm = $this->get_svm();
		$svm->register_global_var($ua_config['session_var_name']);
		$svm->set_global_var($ua_config['session_var_name'], $user);
	}

	
	private function _create_redirect_view($redir = '', $redir_params_arr  = array()) {
		$context = $this->get__context();
		$ua_config = $this->get_ua_config();		
		if (!$redir) {
			$redir = $ua_config['after_login_default_page'];
		}	
		
		$port = $ua_config['after_login_port'];
		if ((is_null($port) || $port == '')) {
			$port = null;
		}
		
		$redir_composer = new Redirect_Composer_Local($this->get__context(), $redir, array(), $ua_config['after_login_protocol'], $port);
		foreach($redir_params_arr as $key => $value) {
			$redir_composer->add_param_pair($key, $value);
		}
		
		$redir_view = new Just_Headers_View();
		$redir_view->add_http_header($redir_composer->get_location($context));
		
		return $redir_view;
	}
	

	private function load_user_reg_settings() {
		$site_config = $this->get__config();
		$conf_file = $site_config->get_conf_dir().'modules/user_auth_basic/user_reg_settings.conf';
		$user_reg_config = new Config_Loader_File($conf_file);

		return $user_reg_config->get_pairs();
	}
	
	
	private function check_ssl_required() {
		$user_auth_config = $this->get_ua_config();
				
		$require_ssl_login = $user_auth_config['require_ssl_login'];
		if ($require_ssl_login && $require_ssl_login != 0) { 
			//if SSL required check if that is the case
			$config = $this->get__config();
			if (strtolower($config->get_current_protocol()) != 'https') {
				throw new Tangra_Module_Exception('HTTPS (SSL) connection required by module configuration. See hidden/conf/machine_specific.conf user_auth_basic section');
			}
		}

	}

	
	private function init_return_to() {
		$context = $this->get__context();
		$ua_config = $this->get_ua_config();
		if ($context->exists_in_get($ua_config['returnto']) && $context->exists_in_get($ua_config['returntoparams'])) {
			$this->return_to = $context->get_from_get($ua_config['returnto']);
			$this->return_to_params_raw = $context->get_from_get($ua_config['returntoparams']);
		} else {
			$this->return_to = $ua_config['after_login_default_page'];
			$this->return_to_params_raw = '';
		}
	}
}